package com.vic.framework;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vic.framework.bean.Data;
import com.vic.framework.bean.Handle;
import com.vic.framework.bean.Param;
import com.vic.framework.bean.View;
import com.vic.framework.helper.BeanHelper;
import com.vic.framework.helper.ConfigHelper;
import com.vic.framework.helper.Controllerhelper;
import com.vic.framework.helper.RequestHelper;
import com.vic.framework.helper.ServletHelper;
import com.vic.framework.helper.UploadHelper;
import com.vic.framework.utils.CoderUtil;
import com.vic.framework.utils.JsonUtil;
import com.vic.framework.utils.ReflectionUtil;
import com.vic.framework.utils.StreamUtil;

/**
 * 请求转发器
 * 
 * @author VIC
 *
 */
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {
	
	private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);

	private static final long serialVersionUID = 1L;

	@Override
	public void init(ServletConfig config) throws ServletException {
		logger.info(".............................DispatcherServlet start  init.............................");
		// 1 初始化相关Helper类
		HelperLoader.init();

		// 2 获取ServletContext
		ServletContext servletContext = config.getServletContext();

		// 3 注册处理JSP的SERVLET
		ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
		jspServlet.addMapping(ConfigHelper.getJspPath() + "*");

		// 4 注册处理静态资源的默认SERVLET
		ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
		defaultServlet.addMapping(ConfigHelper.getStaticPath() + "*");
		UploadHelper.init(servletContext);
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try{
			ServletHelper.init(req, resp);
			
			
			// 1 获取请求方法与请求路径
			String requestMethod = req.getMethod().toLowerCase();

			String requestPath = req.getPathInfo();

			// 2 获取Action处理器 Handle
			Handle handle = Controllerhelper.getHandle(requestMethod, requestPath);
			if (handle == null)
				return;

			// 3 获取Controller class和实例
			Class<?> controllerClass = handle.getControllerClass();

			Object controllerBean = BeanHelper.getBean(controllerClass);

			// 4创建请求参数对象
			Param param;

			if(UploadHelper.isMultipart(req)) {//判断是否是文件上传
				param = UploadHelper.createParam(req);
			}else {
				param = RequestHelper.createParam(req);
			}
			
			// 5 调用Action方法
			
			Method actionMethod = handle.getActionMethod();
			
			Object result;
			
			if(param.isEmpty()) {
				result= ReflectionUtil.invokeMethod(controllerBean, actionMethod);
			}else {
				result= ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
			}
			
			// 6 处理Action方法返回值
			if(result instanceof View) {
				//返回JSP页面
				View view = (View) result;
				String path = view.getPath();
				if(path.startsWith("/")) {
					resp.sendRedirect(req.getContextPath() + path);
				}else {
					Map<String, Object> model = view.getModel();
					for(Map.Entry<String, Object> entry : model.entrySet()) {
						req.setAttribute(entry.getKey(), entry.getValue());
					}
					req.getRequestDispatcher(ConfigHelper.getJspPath() + path).forward(req, resp);
				}
				
			}else if(result instanceof Data) {
				// 返回JSON
				Data data = (Data)result;
				Object model = data.getModel();
				if(model != null) {
					resp.setContentType("application/json");
					resp.setCharacterEncoding("UTF-8");
					PrintWriter writer = resp.getWriter();
					writer.write(JsonUtil.toJson(model));
					writer.flush();
					writer.close();
				}
				
			}
			
			
		}finally{
			ServletHelper.destroy();
		}

	}

	//获得请求中的请求参数
	private Map<String, Object> getParamMap(HttpServletRequest req) throws IOException {
		Map<String, Object> paramMap = new HashMap<String, Object>();

		Enumeration<String> paramNames = req.getParameterNames();

		while (paramNames.hasMoreElements()) {
			String paramName = paramNames.nextElement();
			String paramValue = req.getParameter(paramName);
			paramMap.put(paramName, paramValue);
		}

		String body = CoderUtil.decoderURL(StreamUtil.getString(req.getInputStream()));
		if (StringUtils.isNotEmpty(body)) {
			String[] params = body.split("&");
			if (ArrayUtils.isNotEmpty(params)) {
				for (String param : params) {
					String[] array = param.split("=");
					if (ArrayUtils.isNotEmpty(array) && array.length == 2) {
						paramMap.put(array[0], array[1]);
					}
				}
			}
		}
		return paramMap;
	}

}
